<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Enhanced 3D Environment</title> 
    <!-- 配置Three.js模块导入映射 -->
    <script type="importmap">
     {
        "imports": {
          "three": "./threejs/build/three.module.js",
          "three/addons/": "./threejs/examples/jsm/"
        }
      }
    </script>
    <style>
        /* 基础样式重置与布局设置 */
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        
        body {
            width: 100vw;
            height: 100vh;
            background-color: #0a0a14;
            overflow: hidden;
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
        }
        
        #canvas-container {
            width: 100%;
            height: 100%;
        }
        
        /* 信息面板样式 */
        .info-panel {
            position: fixed;
            bottom: 20px;
            left: 20px;
            background: rgba(10, 10, 20, 0.7);
            backdrop-filter: blur(10px);
            border-radius: 12px;
            padding: 15px;
            color: #e0e0ff;
            font-size: 14px;
            max-width: 320px;
            border: 1px solid rgba(255, 255, 255, 0.1);
            box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
            transition: all 0.3s ease;
        }
        
        .info-panel:hover {
            background: rgba(10, 10, 20, 0.85);
            transform: translateY(-5px);
        }
        
        .info-panel h3 {
            color: #8a94ff;
            margin-bottom: 10px;
            display: flex;
            align-items: center;
            gap: 8px;
        }
        
        .info-panel ul {
            list-style-type: none;
            margin-top: 10px;
        }
        
        .info-panel li {
            margin-bottom: 6px;
            display: flex;
            align-items: center;
            gap: 8px;
        }
        
        .info-panel i {
            color: #8a94ff;
            width: 16px;
        }
        
        /* 加载指示器 */
        .loader {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: #0a0a14;
            display: flex;
            justify-content: center;
            align-items: center;
            z-index: 1000;
            transition: opacity 0.5s ease-out;
        }
        
        .loader.hidden {
            opacity: 0;
            pointer-events: none;
        }
        
        .spinner {
            width: 50px;
            height: 50px;
            border: 5px solid rgba(138, 148, 255, 0.2);
            border-top-color: #8a94ff;
            border-radius: 50%;
            animation: spin 1s linear infinite;
        }
        
        @keyframes spin {
            to { transform: rotate(360deg); }
        }
    </style>
</head>
<body>
    <!-- 加载指示器 -->
    <div class="loader">
        <div class="spinner"></div>
    </div>
    
    <!-- 3D渲染容器 -->
    <div id="canvas-container"></div>
    
    <!-- 信息面板 -->
    <div class="info-panel">
        <h3><i class="fa fa-info-circle"></i> 3D Environment Controls</h3>
        <p>Explore this interactive 3D environment with dynamic elements and effects.</p>
        <ul>
            <li><i class="fa fa-mouse-pointer"></i> Drag to rotate view</li>
            <li><i class="fa fa-search-plus"></i> Scroll to zoom in/out</li>
            <li><i class="fa fa-arrows"></i> Right-click to pan</li>
            <li><i class="fa fa-refresh"></i> Experience day/night cycle</li>
        </ul>
    </div>

    <script type="module">
        // 导入Three.js核心模块和必要组件
        import * as THREE from 'three';
        import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
        import { Sky } from 'three/addons/objects/Sky.js';
        import { EffectComposer } from 'three/addons/postprocessing/EffectComposer.js';
        import { RenderPass } from 'three/addons/postprocessing/RenderPass.js';
        import { BloomPass } from 'three/addons/postprocessing/BloomPass.js';
        import { UnrealBloomPass } from 'three/addons/postprocessing/UnrealBloomPass.js';

        // 初始化场景核心组件
        const container = document.getElementById('canvas-container');
        const loader = document.querySelector('.loader');
        
        // 创建场景实例 - 所有3D对象的容器
        const scene = new THREE.Scene();
        
        // 创建透视相机 - 模拟人眼视角
        const camera = new THREE.PerspectiveCamera(
            55, 
            container.clientWidth / container.clientHeight, 
            0.1, 
            1000000000
        );
        camera.position.set(1200, 800, 1500);
        
        // 创建WebGL渲染器
        const renderer = new THREE.WebGLRenderer({
            antialias: true,
            alpha: true,
            logarithmicDepthBuffer: true
        });
        renderer.setSize(container.clientWidth, container.clientHeight);
        renderer.useLegacyLights = false;
        renderer.shadowMap.enabled = true;
        renderer.shadowMap.type = THREE.PCFSoftShadowMap; // 更柔和的阴影
        renderer.toneMapping = THREE.ACESFilmicToneMapping; // 电影级色调映射
        renderer.toneMappingExposure = 1.2;
        container.appendChild(renderer.domElement);
        
        // 初始化后处理 composer
        const composer = new EffectComposer(renderer);
        const renderPass = new RenderPass(scene, camera);
        composer.addPass(renderPass);
        
        // 添加泛光效果
        const bloomPass = new UnrealBloomPass(
            new THREE.Vector2(window.innerWidth, window.innerHeight),
            0.7, // 强度
            0.4, // 半径
            0.85 // 阈值
        );
        composer.addPass(bloomPass);
        
        // 创建轨道控制器
        const controls = new OrbitControls(camera, renderer.domElement);
        controls.enableDamping = true;
        controls.dampingFactor = 0.05;
        controls.enableZoom = true;
        controls.zoomSpeed = 0.7;
        controls.enablePan = true;
        controls.panSpeed = 0.5;
        controls.maxPolarAngle = Math.PI * 0.85; // 限制垂直旋转角度
        
        // 场景光照系统配置
        // 添加环境光
        const ambientLight = new THREE.AmbientLight(0x1a237e, 0.6);
        scene.add(ambientLight);
        
        // 添加方向光 - 模拟太阳光
        const directionalLight = new THREE.DirectionalLight(0xffffff, 1.2);
        directionalLight.position.set(100, 200, 80);
        directionalLight.castShadow = true;
        
        // 优化阴影质量
        directionalLight.shadow.mapSize.width = 4096;
        directionalLight.shadow.mapSize.height = 4096;
        directionalLight.shadow.camera.near = 50;
        directionalLight.shadow.camera.far = 2000;
        directionalLight.shadow.camera.left = -1000;
        directionalLight.shadow.camera.right = 1000;
        directionalLight.shadow.camera.top = 1000;
        directionalLight.shadow.camera.bottom = -1000;
        directionalLight.shadow.radius = 4; // 软阴影半径
        scene.add(directionalLight);
        
        // 添加点光源用于强调效果
        const pointLight = new THREE.PointLight(0x8a94ff, 0.8, 1000);
        pointLight.position.set(0, 300, 0);
        pointLight.castShadow = true;
        pointLight.shadow.mapSize.set(2048, 2048);
        scene.add(pointLight);

        // 创建天空盒 - 模拟大气效果
        const sky = new Sky();
        sky.scale.setScalar(450000);
        
        const skyUniforms = sky.material.uniforms;
        const sunPosition = new THREE.Vector3();
        scene.add(sky);

        // 创建星空背景
        function createStars(count) {
            const starsGeometry = new THREE.BufferGeometry();
            const positions = new Float32Array(count * 3);
            
            for (let i = 0; i < count; i++) {
                const i3 = i * 3;
                // 分布在一个大球体内
                const radius = 5000 + Math.random() * 5000;
                const theta = Math.random() * Math.PI * 2;
                const phi = Math.random() * Math.PI;
                
                positions[i3] = radius * Math.sin(phi) * Math.cos(theta);
                positions[i3 + 1] = radius * Math.sin(phi) * Math.sin(theta);
                positions[i3 + 2] = radius * Math.cos(phi);
            }
            
            starsGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
            
            // 创建星星材质 - 带闪烁效果
            const starsMaterial = new THREE.ShaderMaterial({
                uniforms: {
                    time: { value: 0 },
                    color: { value: new THREE.Color(0xffffff) }
                },
                vertexShader: `
                    attribute float size;
                    uniform float time;
                    varying float vAlpha;
                    
                    void main() {
                        vAlpha = 0.5 + 0.5 * sin(time + position.x * 0.01);
                        gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
                        gl_PointSize = 2.0 * (1.0 - gl_Position.z / gl_Position.w * 0.0001);
                    }
                `,
                fragmentShader: `
                    uniform vec3 color;
                    varying float vAlpha;
                    
                    void main() {
                        float alpha = vAlpha * (1.0 - length(gl_PointCoord - vec2(0.5)) * 2.0);
                        gl_FragColor = vec4(color, alpha);
                    }
                `,
                transparent: true,
                blending: THREE.AdditiveBlending,
                depthWrite: false
            });
            
            const stars = new THREE.Points(starsGeometry, starsMaterial);
            return stars;
        }
        
        const stars = createStars(15000);
        scene.add(stars);

        /**
         * 自定义无限网格辅助类
         */
        class AdvancedGridHelper extends THREE.Mesh {
            constructor(
                minorSize = 10, 
                majorSize = 100, 
                color = new THREE.Color(0x8899aa), 
                maxDistance = 10000, 
                axes = 'xzy'
            ) {
                const geometry = new THREE.PlaneGeometry(2, 2, 1, 1);
                const planeAxes = axes.substring(0, 2);
                
                const material = new THREE.ShaderMaterial({
                    side: THREE.DoubleSide,
                    uniforms: {
                        uMinorSize: { value: minorSize },
                        uMajorSize: { value: majorSize },
                        uColor: { value: color },
                        uMaxDistance: { value: maxDistance },
                        uTime: { value: 0 },
                        uFogColor: { value: scene.background instanceof THREE.Color ? scene.background : new THREE.Color(0x000000) }
                    },
                    transparent: true,
                    vertexShader: `
                        varying vec3 vWorldPos;
                        uniform float uMaxDistance;
                        
                        void main() {
                            vec3 pos = position.${axes} * uMaxDistance;
                            pos.${planeAxes} += cameraPosition.${planeAxes};
                            vWorldPos = pos;
                            gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
                        }
                    `,
                    fragmentShader: `
                        varying vec3 vWorldPos;
                        uniform float uMinorSize;
                        uniform float uMajorSize;
                        uniform vec3 uColor;
                        uniform float uMaxDistance;
                        uniform float uTime;
                        uniform vec3 uFogColor;
                        
                        float getGridLine(float size) {
                            vec2 gridCoords = vWorldPos.${planeAxes} / size;
                            vec2 grid = abs(fract(gridCoords - 0.5) - 0.5) / fwidth(gridCoords);
                            return 1.0 - min(min(grid.x, grid.y), 1.0);
                        }
                        
                        void main() {
                            float distanceFactor = 1.0 - min(
                                distance(cameraPosition.${planeAxes}, vWorldPos.${planeAxes}) / uMaxDistance, 
                                1.0
                            );
                            
                            float minorGrid = getGridLine(uMinorSize);
                            float majorGrid = getGridLine(uMajorSize);
                            
                            // 添加微妙的网格动画
                            float animation = sin(uTime * 0.1 + vWorldPos.x * 0.01) * 0.1 + 0.9;
                            float gridAlpha = mix(majorGrid, minorGrid, minorGrid) * pow(distanceFactor, 3.0) * animation;
                            gridAlpha = mix(gridAlpha * 0.5, gridAlpha, majorGrid);
                            
                            // 应用雾效混合
                            float fogFactor = pow(distanceFactor, 5.0);
                            vec3 finalColor = mix(uFogColor, uColor, fogFactor);
                            
                            gl_FragColor = vec4(finalColor, gridAlpha);
                            
                            if (gl_FragColor.a <= 0.0) discard;
                        }
                    `,
                    extensions: {
                        derivatives: true
                    }
                });
                
                super(geometry, material);
                this.frustumCulled = false;
            }
            
            update(deltaTime) {
                if (this.material.uniforms.uTime) {
                    this.material.uniforms.uTime.value += deltaTime;
                }
            }
        }

        // 创建并添加无限网格到场景
        const gridHelper = new AdvancedGridHelper(
            15,    // 次要网格间距
            150,   // 主要网格间距
            new THREE.Color(0x607d8b),  // 网格颜色
            12000  // 最大可见距离
        );
        scene.add(gridHelper);

        // 创建漂浮几何体
        function createFloatingObjects(count) {
            const objects = new THREE.Group();
            const geometries = [
                new THREE.IcosahedronGeometry(10, 1),
                new THREE.TorusKnotGeometry(8, 2.5, 100, 16),
                new THREE.OctahedronGeometry(12, 1),
                new THREE.TetrahedronGeometry(14, 1)
            ];
            
            // 创建发光材质
            const glowMaterial = new THREE.ShaderMaterial({
                uniforms: {
                    color: { value: new THREE.Color(0x8a94ff) },
                    glowColor: { value: new THREE.Color(0x4a54ff) },
                    intensity: { value: 1.0 },
                    time: { value: 0 }
                },
                vertexShader: `
                    uniform float time;
                    varying vec3 vNormal;
                    
                    void main() {
                        vNormal = normalize(normalMatrix * normal);
                        // 添加微妙的脉动效果
                        float pulse = 1.0 + 0.1 * sin(time + position.x * 0.1);
                        vec3 pos = position * pulse;
                        gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
                    }
                `,
                fragmentShader: `
                    uniform vec3 color;
                    uniform vec3 glowColor;
                    uniform float intensity;
                    varying vec3 vNormal;
                    
                    void main() {
                        float glow = pow(1.0 - abs(dot(vNormal, vec3(0, 0, 1))), 3.0) * intensity;
                        gl_FragColor = vec4(mix(color, glowColor, glow), 1.0);
                    }
                `,
                side: THREE.FrontSide,
                transparent: true
            });
            
            // 创建光晕材质
            const haloMaterial = new THREE.ShaderMaterial({
                uniforms: {
                    color: { value: new THREE.Color(0x8a94ff) },
                    time: { value: 0 }
                },
                vertexShader: `
                    uniform float time;
                    varying vec3 vNormal;
                    
                    void main() {
                        vNormal = normalize(normalMatrix * normal);
                        // 更大的脉动效果
                        float pulse = 1.5 + 0.3 * sin(time + position.x * 0.1);
                        vec3 pos = position * pulse;
                        gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
                    }
                `,
                fragmentShader: `
                    uniform vec3 color;
                    varying vec3 vNormal;
                    
                    void main() {
                        float alpha = pow(1.0 - abs(dot(vNormal, vec3(0, 0, 1))), 2.0);
                        gl_FragColor = vec4(color, alpha * 0.3);
                    }
                `,
                side: THREE.BackSide,
                transparent: true,
                blending: THREE.AdditiveBlending
            });
            
            for (let i = 0; i < count; i++) {
                const geometry = geometries[Math.floor(Math.random() * geometries.length)].clone();
                const size = 5 + Math.random() * 15;
                geometry.scale(size, size, size);
                
                // 创建物体和光晕
                const mesh = new THREE.Mesh(geometry, glowMaterial.clone());
                const halo = new THREE.Mesh(geometry, haloMaterial.clone());
                
                // 随机位置和颜色
                const range = 800;
                mesh.position.set(
                    (Math.random() - 0.5) * range,
                    50 + Math.random() * 300,
                    (Math.random() - 0.5) * range
                );
                halo.position.copy(mesh.position);
                
                // 随机颜色
                const hue = 0.6 + Math.random() * 0.2; // 蓝色到紫色范围
                const color = new THREE.Color().setHSL(hue, 0.8, 0.6);
                mesh.material.uniforms.color.value.copy(color);
                mesh.material.uniforms.glowColor.value.copy(color.clone().multiplyScalar(1.5));
                
                halo.material.uniforms.color.value.copy(color);
                
                // 添加动画属性
                mesh.userData.rotationSpeed = {
                    x: (Math.random() - 0.5) * 0.01,
                    y: (Math.random() - 0.5) * 0.01
                };
                mesh.userData.orbit = {
                    radius: Math.random() * 50,
                    speed: (Math.random() - 0.5) * 0.005,
                    angle: Math.random() * Math.PI * 2
                };
                mesh.userData.initialPos = mesh.position.clone();
                
                objects.add(mesh);
                objects.add(halo);
            }
            
            return {
                group: objects,
                update: function(deltaTime) {
                    objects.children.forEach(child => {
                        if (child.userData.rotationSpeed) {
                            // 旋转
                            child.rotation.x += child.userData.rotationSpeed.x * deltaTime * 60;
                            child.rotation.y += child.userData.rotationSpeed.y * deltaTime * 60;
                            
                            // 轨道运动
                            child.userData.orbit.angle += child.userData.orbit.speed * deltaTime * 60;
                            const x = Math.cos(child.userData.orbit.angle) * child.userData.orbit.radius;
                            const z = Math.sin(child.userData.orbit.angle) * child.userData.orbit.radius;
                            child.position.x = child.userData.initialPos.x + x;
                            child.position.z = child.userData.initialPos.z + z;
                        }
                        
                        // 更新时间 uniforms
                        if (child.material.uniforms.time) {
                            child.material.uniforms.time.value += deltaTime;
                        }
                    });
                }
            };
        }
        
        const floatingObjects = createFloatingObjects(25);
        scene.add(floatingObjects.group);

        // 创建粒子系统
        function createParticleSystem() {
            const particlesGeometry = new THREE.BufferGeometry();
            const count = 10000;
            const positions = new Float32Array(count * 3);
            const velocities = new Float32Array(count * 3);
            
            for (let i = 0; i < count; i++) {
                const i3 = i * 3;
                // 分布在一个大范围内
                const range = 1500;
                positions[i3] = (Math.random() - 0.5) * range;
                positions[i3 + 1] = Math.random() * 500; // 只在地面以上
                positions[i3 + 2] = (Math.random() - 0.5) * range;
                
                // 初始速度
                velocities[i3] = (Math.random() - 0.5) * 0.1;
                velocities[i3 + 1] = (Math.random() - 0.5) * 0.1;
                velocities[i3 + 2] = (Math.random() - 0.5) * 0.1;
            }
            
            particlesGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
            particlesGeometry.setAttribute('velocity', new THREE.BufferAttribute(velocities, 3));
            
            // 创建粒子材质
            const material = new THREE.ShaderMaterial({
                uniforms: {
                    color: { value: new THREE.Color(0x8a94ff) },
                    time: { value: 0 },
                    cameraPos: { value: camera.position }
                },
                vertexShader: `
                    attribute vec3 velocity;
                    uniform float time;
                    uniform vec3 cameraPos;
                    varying float vDistance;
                    
                    void main() {
                        // 粒子移动
                        vec3 pos = position + velocity * time * 10.0;
                        
                        // 计算与相机的距离用于大小衰减
                        vDistance = distance(pos, cameraPos);
                        
                        gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
                        gl_PointSize = 2.0 * (1.0 - vDistance / 5000.0);
                    }
                `,
                fragmentShader: `
                    uniform vec3 color;
                    varying float vDistance;
                    
                    void main() {
                        float alpha = 0.5 * (1.0 - vDistance / 5000.0);
                        alpha *= (1.0 - length(gl_PointCoord - vec2(0.5)) * 2.0);
                        gl_FragColor = vec4(color, alpha);
                    }
                `,
                transparent: true,
                blending: THREE.AdditiveBlending,
                depthWrite: false
            });
            
            const particles = new THREE.Points(particlesGeometry, material);
            
            return {
                mesh: particles,
                update: function(deltaTime) {
                    particles.material.uniforms.time.value += deltaTime;
                    particles.material.uniforms.cameraPos.value.copy(camera.position);
                }
            };
        }
        
        const particleSystem = createParticleSystem();
        scene.add(particleSystem.mesh);

        // 日夜循环动画控制器
        let dayNightCycle = {
            time: 0,
            period: 60, // 60秒一个周期
            update: function(deltaTime) {
                this.time += deltaTime;
                if (this.time > this.period) this.time = 0;
                
                const phase = this.time / this.period;
                const isDay = phase < 0.5;
                const cycleProgress = isDay ? phase * 2 : 2 - phase * 2;
                
                // 太阳位置动画 (使用球坐标)
                const sunElevation = Math.PI/4 + Math.PI/4 * Math.cos(phase * Math.PI * 2 + Math.PI);
                const sunAzimuth = phase * Math.PI * 2;
                
                sunPosition.setFromSphericalCoords(
                    1, 
                    sunElevation,  // 高度角
                    sunAzimuth     // 方位角
                );
                
                skyUniforms.sunPosition.value.copy(sunPosition);
                
                // 调整天空参数
                skyUniforms.rayleigh.value = 3.2 * cycleProgress;
                skyUniforms.mieCoefficient.value = 0.005 + 0.002 * (1 - cycleProgress);
                
                // 调整光照
                const lightIntensity = 0.3 + 0.9 * cycleProgress;
                directionalLight.intensity = lightIntensity;
                directionalLight.color.setHSL(0.1 + 0.05 * (1 - cycleProgress), 1, 0.7 * cycleProgress + 0.1);
                
                // 调整环境光
                ambientLight.intensity = 0.2 + 0.4 * cycleProgress;
                ambientLight.color.setHSL(0.6, 0.5, 0.2 * cycleProgress + 0.05);
                
                // 调整背景色 (星空/天空)
                const nightColor = new THREE.Color(0x0a0a14);
                const dayColor = new THREE.Color(0x87CEEB).multiplyScalar(0.8);
                scene.background = nightColor.clone().lerp(dayColor, cycleProgress);
                
                // 更新网格雾色
                if (gridHelper.material.uniforms.uFogColor) {
                    gridHelper.material.uniforms.uFogColor.value.copy(scene.background);
                }
                
                // 调整星星可见度
                stars.material.opacity = 1 - cycleProgress;
                
                // 调整光晕效果
                bloomPass.strength = 0.5 + 0.5 * (1 - cycleProgress);
            }
        };

        /**
         * 动画循环函数
         */
        function animate() {
            requestAnimationFrame(animate);
            
            const deltaTime = 1/60; // 固定时间步长
            
            // 更新控制器
            controls.update();
            
            // 更新日夜循环
            dayNightCycle.update(deltaTime);
            
            // 更新网格动画
            gridHelper.update(deltaTime);
            
            // 更新漂浮物体
            floatingObjects.update(deltaTime);
            
            // 更新粒子系统
            particleSystem.update(deltaTime);
            
            // 更新星星动画
            if (stars.material.uniforms.time) {
                stars.material.uniforms.time.value += deltaTime;
            }
            
            // 渲染场景
            composer.render();
        }
        
        // 启动动画循环
        animate();

        /**
         * 窗口大小变化处理函数
         */
        function handleResize() {
            renderer.setSize(container.clientWidth, container.clientHeight);
            composer.setSize(container.clientWidth, container.clientHeight);
            camera.aspect = container.clientWidth / container.clientHeight;
            camera.updateProjectionMatrix();
        }
        
        // 监听窗口大小变化事件
        window.addEventListener('resize', handleResize);
        
        // 隐藏加载指示器
        window.addEventListener('load', () => {
            setTimeout(() => {
                loader.classList.add('hidden');
            }, 800);
        });
    </script>
</body>
</html>
